<script setup xmlns="http://www.w3.org/1999/html">
import { ref, reactive, computed, onMounted } from "vue";
import axios from "axios";
import SelectMaterialDialog from "./components/SelectMaterialDialog.vue";
import md5 from "crypto-js/md5";
import { get_duration, extractDuration, saveBlobVideo } from "./util/index";
import NestedRadio from "./components/NestedRadio.vue";
const token_stroage = ref("");
const getstorage = () => {
  return new Promise((resolve, reject) => {
    // if(!window.ipcRenderer){
    //   token_stroage.value = 'bcaac94a-3c17-4cfb-816b-e4d7e32bcb1b' // company 453b5079-5941-4b09-9758-ffc55688067b
    //   resolve()
    // }
    window.ipcRenderer
      .invoke("send_storage")
      .then((result) => {
        const localStorageData = JSON.parse(result);
        token_stroage.value = localStorageData.token;
        Object.entries(localStorageData).forEach(([key, value]) => {
          localStorage.setItem(key, value);
        });
        resolve();
      })
      .catch((err) => {
        console.log("errr", err);
        reject(err);
      });
  });
};
const count = ref(0);
const hightSet = ref(false)
const musicList = ref([]);
const current = ref("");
const fault_video = ref([]);
const onDelFragVideo = (fragment) => {
  videosDialog.dataList[fragment] = []
  fileList.value[fragment] = [];
}
const onUploadMusicRemove = (file) => {
  const removedFileIndex = musicList.value.indexOf(file);
  musicList.value.splice(removedFileIndex, 1);
};
const onhandleMusicRequest = (e) => {
  musicList.value.push(e.file);
};
const maskList = ref([]);
const onUploadMaskRemove = (file) => {
  const removedFileIndex = maskList.value.indexOf(file);
  maskList.value.splice(removedFileIndex, 1);
};
const onhandleMaskRequest = (e) => {
  maskList.value.push(e.file);
};
const fragmentArr = ref(["A"]);
const fragmentList = [
  "A",
  "B",
  "C",
  "D",
  "E",
  "F",
  "G",
  "H",
  "I",
  "J",
  "K",
  "L",
  "M",
  "N",
  "O",
  "P",
  "Q",
  "R",
  "S",
  "T",
  "U",
  "V",
  "W",
  "X",
  "Y",
  "Z",
];
const onAddFragment = () => {
  fragmentList[fragmentArr.value.length] &&
    fragmentArr.value.push(fragmentList[fragmentArr.value.length]);
};
const videoType = {
  // 老系统素材
  origin: 0,
  // 云视频系统
  yunshipin: 1,
};
const loading = ref(false);
const yunloading = ref({});
// 判断所有的云视频都下载到本地
const adjustloaded = () => {
  let loading = false;
  for (let i in yunloading.value) {
    if (yunloading.value[i]) {
      loading = true;
    }
  }
  return loading;
};
const ruleFormRef = ref();
const videosDialog = reactive({
  visible: false,
  type: videoType.origin,
  dataList: {},
  fragment: "A",
});
const handleCyjbQsscFileRemove = (item, fragment) => {
  if (loading.value) {
    return;
  }
  videosDialog.dataList[fragment] = videosDialog.dataList[fragment].filter(
    (value) => item.id != value.id
  );
};

const changeCyjbQsscVisible = (value) => {
  videosDialog.visible = value;
};
const changeCyjbQsscData = async (value, fragment) => {
  const old = videosDialog.dataList[fragment]
    ? videosDialog.dataList[fragment].filter((item) => {
        return item.type !== videosDialog.type;
      })
    : [];
  const files = [...old, ...(value || [])];
  const videos = [];
  videosDialog.visible = false;
  yunloading.value[fragment] = true;
  for (let i = 0; i < files.length; i++) {
    if (files[i].localData) {
      videos.push(files[i]);
    } else {
      const result = await window.ipcRenderer.invoke(
        "download-video",
        files[i].url
      );
      videos.push({
        ...files[i],
        url: result,
        localData: true,
        net_url: files[i].url,
      });
    }
  }
  yunloading.value[fragment] = false;
  videosDialog.dataList[fragment] = [...videos];
};
const { createFFmpeg, fetchFile } = FFmpeg;
const form = reactive({
  size: "0",
  number: 1,
  editor_name: "",
  sound: 30,
  video_name: "",
  product_id: "",
  cloud_task_id: "",
});
const handleVisible = (value) => {
  videosDialog.type = videoType.yunshipin;
  videosDialog.visible = true;
  videosDialog.fragment = value;
};
const completed = ref(0);
const single = ref(1);
const saveWay = ref(1);
const single_count = ref(1);
const rules = reactive({
  number: [{ required: true, message: "请选择次数", trigger: "blur" }],
  editor_name: [
    { required: true, message: "请输入剪辑师名称", trigger: "blur" },
  ],
});

const blob_list = ref([]);
const fileList = ref({});
const progressWidth = computed(() => {
  return `${(completed.value / form.number) * 100}`;
});
let ffmpeg;
const onhandleRequest = (e) => {
  const type = e.data;
  if (!fileList.value[type]) {
    fileList.value[type] = [e.file];
  } else {
    fileList.value[type].push(e.file);
  }
};
const onUploadRemove = (file, fragment) => {
  if (loading.value) {
    return;
  }
  const removedFileIndex = fileList.value[fragment].indexOf(file);
  fileList.value[fragment].splice(removedFileIndex, 1);
};
const blob2Base64 = (blob) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(blob);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
};
// 新视频合并
async function processVideoBlobs(videoBlobs) {
  console.log("ffmpeg1--", ffmpeg);
  if (!ffmpeg.isLoaded()) {
    await ffmpeg.load();
  }
  let duration = 0;
  let format_isfalut;
  current.value = "";
  for (let index = 0; index < videoBlobs.length; index++) {
    console.log("step2-3-1");
    const blob = videoBlobs[index];
    console.log("blob");
    let video;
    if (blob.path) {
      try {
        video = await fetchFile(blob);
        current.value += blob.path + ",";
      } catch (err) {
        console.log("err--1", err);
      }
    } else {
      try {
        video = await window.fs.readFileSync(blob.url);
        current.value += blob.name + ",";
      } catch (err) {
        console.log("err--2", err);
      }
    }
    console.log("step2-3-2");
    // duration += await get_duration(video);
    console.log("step2-3-3");
    let command = [
      "-i",
      `input${index}.mp4`,
      "-c:v",
      "copy",
      "-c:a",
      "copy",
      "-bsf:v",
      "h264_mp4toannexb",
      `input${index}.ts`,
    ];
    if (video) {
      await ffmpeg.FS("writeFile", `input${index}.mp4`, video);
    } else {
      format_isfalut = true;
    }
    ffmpeg.setLogger(({ type, message }) => {
      if (message.includes("Duration")) {
        duration += extractDuration(message);
        console.log("duration", duration);
      }
      if (message.includes("hevc")) {
        format_isfalut = true;
        fault_video.value.push(blob.path || blob.url + "[格式错误]");
        // command = [
        //   "-i",
        //   `input${index}.mp4`,
        //   "-c:v",
        //   "libx264",
        //   "-c:a",
        //   "copy",
        //   "-bsf:v",
        //   "h264_mp4toannexb",
        //   `input${index}.ts`,
        // ];
      }
    });
    try {
      await ffmpeg.run("-i", `input${index}.mp4`);
    } catch (err) {
      console.log("mp4_info", err);
    }
    console.log("command----", command);
    ffmpeg.setLogger(() => {});
    if (format_isfalut) {
      await ffmpeg.FS("unlink", `input${index}.mp4`);
    } else {
      try {
        await ffmpeg.run(...command);
      } catch (err) {
        console.log("step2-3-4-before", err);
      }
    }
    console.log("step2-3-4");
  }
  return { duration, format_isfalut };
}
async function mergeVideosWithBackgroundMusic(videoBlobs, outputName, time) {
  console.log(time);
  if (ffmpeg && time % 2 == 1) {
    await ffmpeg.exit();
  }
  console.log("step2-1");
  if (time % 2 == 1) {
    ffmpeg = createFFmpeg({
      log: false,
    });
    await ffmpeg.load();
  }
  console.log("step2-2");

  console.log("step2-3");
  // 将视频和音频文件写入FFmpeg的文件系统
  const { duration, format_isfalut } = await processVideoBlobs(videoBlobs);
  if (format_isfalut) {
    completed.value = time;
    return;
  }
  console.log("step2-4");
  const audio = randomData(musicList.value);
  console.log("step2-5");
  const mask = randomData(maskList.value);
  console.log("step2-6");
  if (audio && audio.path) {
    await ffmpeg.FS("writeFile", "background.mp3", await fetchFile(audio));
  }
  if (mask && mask.path) {
    // let command = [
    //   "-i",
    //   "mask_video.mp4",
    //   "-c:v",
    //   "copy",
    //   "-c:a",
    //   "copy",
    //   "-bsf:v",
    //   "h264_mp4toannexb",
    //   "mask_video.ts",
    // ];
    // let mask_falut;
    await ffmpeg.FS("writeFile", "mask_video.png", await fetchFile(mask));
    // ffmpeg.setLogger(({ type, message }) => {
    //   if (message.includes("hevc")) {
    //     mask_falut = true;
    //     fault_video.value.push(mask.path + "[格式错误]");
    //     // command = [
    //     //   "-i",
    //     //   "mask_video.mp4",
    //     //   "-c:v",
    //     //   "libx264",
    //     //   "-c:a",
    //     //   "copy",
    //     //   "-bsf:v",
    //     //   "h264_mp4toannexb",
    //     //   "mask_video.ts",
    //     // ];
    //   }
    // });
    // await ffmpeg.run("-i", "mask_video.mp4");
    // if (mask_falut) {
    //   await ffmpeg.FS("unlink", "mask_video.mp4");
    //   completed.value = time;
    //   return;
    // }
    // ffmpeg.setLogger(() => {});
    // await ffmpeg.run(...command);
  }
  // 创建一个文本文件，包含用于合并视频的FFmpeg命令
  const fileList = videoBlobs
    .map((blob, index) => `file 'input${index}.ts'`)
    .join("\n");
  console.log(fileList);
  await ffmpeg.FS("writeFile", "file_list.txt", fileList);
  console.log("step2-7");
  // 运行FFmpeg命令来合并视频并添加背景音乐
  let ffmpeg_code;
  if (audio && audio.path) {
    // if (mask && mask.path) {
      // ffmpeg_code = [
      //   "-f",
      //   "concat",
      //   "-safe",
      //   "0",
      //   "-i",
      //   "file_list.txt",
      //   "-i",
      //   "mask_video.ts",
      //   "-i",
      //   "background.mp3",
      //   "-filter_complex",
      //   "[0:v][1:v]overlay[outv];[2:a][0:a]amix=inputs=2:duration=longest[a]",
      //   "-vsync",
      //   "vfr",
      //   "-map",
      //   "[outv]",
      //   "-map",
      //   "[a]",
      //   "-c:v",
      //   "libx264",
      //   "-c:a",
      //   "aac",
      //   "-t",
      //   duration.toString(),
      //   outputName,
      // ];
    // } else {
      ffmpeg_code = [
        "-f",
        "concat",
        "-safe",
        "0",
        "-i",
        "file_list.txt",
        "-i",
        "background.mp3",
        "-filter_complex",
        "[0:a][1:a]amix=inputs=2:duration=longest[a]",
        "-vsync",
        "vfr",
        "-map",
        "0:v",
        "-map",
        "[a]",
        "-c:v",
        "copy",
        "-c:a",
        "aac",
        "-strict",
        "experimental",
        "-t",
        duration.toString(),
        outputName,
      ];
    // }
  } else {
    // if (mask && mask.path) {
    //   ffmpeg_code = [
    //     "-f",
    //     "concat",
    //     "-i",
    //     "file_list.txt",
    //     "-i",
    //     "mask_video.ts",
    //     "-filter_complex",
    //     "[0:v][1:v]overlay[outv]",
    //     "-vsync",
    //     "vfr",
    //     "-map",
    //     "[outv]",
    //     "-map",
    //     "0:a",
    //     "-c:v",
    //     "libx264",
    //     "-c:a",
    //     "copy",
    //     "-t",
    //     duration.toString(),
    //     outputName,
    //   ];
    // } else {
      ffmpeg_code = [
        "-f",
        "concat",
        "-i",
        "file_list.txt",
        "-vsync",
        "vfr",
        "-codec",
        "copy",
        "-absf",
        "aac_adtstoasc",
        outputName,
      ];
    // }
  }
  console.log(ffmpeg_code);
  try {
    await ffmpeg.run(...ffmpeg_code);
  } catch (err) {
    console.log("step2-8-before", err);
  }
  // let selectOutName = 'select_' + outputName
  // const select_code = [
  //   "-i",
  //   outputName,
  //   "-vf",
  //   "select='if(gt(random(0), 0.05), 1, 0)', setpts=N/FRAME_RATE/TB",
  //   "-c:v",
  //   "libx264",
  //   selectOutName
  // ]
  // try {
  //   await ffmpeg.run(...select_code);
  // } catch (err) {
  //   console.log("select_code", err);
  // }
  let data;
  if (mask && mask.path) {
    ffmpeg_code = [
        "-i",
        outputName,
        "-i",
        "mask_video.png",
        "-filter_complex",
        "[0:v][1:v] overlay=0:0:enable='between(t,0," + duration.toString()+ ")'",
        "-c:a",
        "copy",
        "mask_output.mp4"
    ];
    try {
      console.log(ffmpeg_code);
      await ffmpeg.run(...ffmpeg_code);
    } catch (err) {
      console.log("step2-9-before", err);
    }
    data = await ffmpeg.FS("readFile", "mask_output.mp4");
  } else {
    data = await ffmpeg.FS("readFile", outputName);
  }
  console.log("step2-8");
  // 读取合并后的视频文件

  console.log("step2-9");
  // 创建一个Blob对象
  const videoBlob = new Blob([data.buffer], { type: "video/mp4" });
  console.log("step2-10");
  // 清理FFmpeg的文件系统
  for (let i = 0; i < videoBlobs.length; i++) {
    await ffmpeg.FS("unlink", `input${i}.ts`);
    await ffmpeg.FS("unlink", `input${i}.mp4`);
  }
  console.log("step2-11");
  if (audio && audio.path) {
    await ffmpeg.FS("unlink", "background.mp3");
  }
  console.log("step2-12");
  if (mask && mask.path) {
    // await ffmpeg.FS("unlink", "mask_video.ts");
    // await ffmpeg.FS("unlink", "mask_video.mp4");
    // await ffmpeg.FS("unlink", "mask_output.mp4");
  }
  console.log("step2-13");
  await ffmpeg.FS("unlink", "file_list.txt");
  await ffmpeg.FS("unlink", outputName);
  // await ffmpeg.FS("unlink", selectOutName);
  console.log("step2-14");
  // const videoData = await blob2Base64(
  //   new Blob([videoBlob], { type: "video/mp4" })
  // );
  // blob_list.value.push(videoData);
  completed.value = time;
  return {videoBlob, bufferData: data.buffer};
}
// 获取标签页面
const deleteValue = (id) => {
  const item = getItemContainingSubItem(id);
  if (item) {
    const index = item.tags.findIndex((subItem) => subItem.id === id);
    if (index !== -1) {
      if (selectedValues.value.includes(id)) {
        selectedValues.value = selectedValues.value.filter(
          (value) => value !== id
        );
      }
    }
  }
};
const getItemContainingSubItem = (id) => {
  return label_list.value.find(
    (item) => item.tags && item.tags.some((subItem) => subItem.id === id)
  );
};
const getSubItemName = (id) => {
  const item = getItemContainingSubItem(id);
  if (item) {
    const subItem = item.tags && item.tags.find((subItem) => subItem.id === id);
    if (subItem) {
      return subItem.name;
    }
  }
  return "";
};
const selectedLabel = ref(null);
const selectedValues = ref([]);
const selectItem = (item) => {
  selectedLabel.value = item;
};
const selectedSubItems = computed(() => {
  if (selectedLabel.value) {
    return selectedLabel.value.tags;
  }
  return [];
});
const label_list = ref([]);
const getlabels = () => {
  const token = token_stroage.value;
  const data = {
    token,
  };
  axios
    .post("https://qianniu.bingdou.site/v1/cloud/manage/tag_group/list", data)
    .then((response) => {
      if (response.data && response.data.code === 0) {
        label_list.value = response.data.data.list;
      }
    });
};
// 获取分类列表
const classification = ref([]);
const getClassification = () => {
  const token = token_stroage.value;
  const data = {
    token,
    type: 1,
  };
  axios
    .post(
      "https://qianniu.bingdou.site/v1/cloud/client/classification/list",
      data
    )
    .then((response) => {
      if (response.data && response.data.code === 0) {
        classification.value = response.data.data;
      }
    })
    .catch((error) => {
      console.error(error);
      ElMessage.error("获取分类列表失败");
    });
};
const oss_url = ref("");
//获取上传视频的地址
const getOssUrl = () => {
  const token = token_stroage.value;
  const data = {
    token,
  };
  axios
    .post("https://qianniu.bingdou.site/v1/merchant/company/oss_url", data)
    .then((response) => {
      if (response.data && response.data.code === 0) {
        oss_url.value = response.data.data.url;
        // oss_url.value = "https://neibu.bingdou.site:30001";
      }
    })
    .catch((error) => {
      console.error(error);
      ElMessage.error("获取上传地址失败");
    });
};
function difference(array1, array2) {
  console.log(array1);
  console.log(array2);
  return array1.filter((item) => array2.indexOf(item) === -1);
}
// 获取剩余生成次数
const getCountFunction = () => {
  console.log("token_stroage", token_stroage.value);
  const token = token_stroage.value;
  const data = {
    token,
  };
  axios
    .post("https://qianniu.bingdou.site/v1/video/query_number", data)
    .then((response) => {
      if (response.data && response.data.code === 0) {
        count.value = response.data.data.number;
      }
    })
    .catch((error) => {
      console.error(error);
      ElMessage.error("获取生成次数失败");
    });
};

// 获取产品列表
const productList = ref([]);
const getProductList = () => {
  const token = token_stroage.value;
  const data = {
    token,
    page: 1,
    page_size: 9999,
  };
  axios
    .post("https://qianniu.bingdou.site/v1/merchant/product/list", data)
    .then((response) => {
      if (response.data && response.data.code === 0) {
        productList.value = response.data.data.list;
      }
    })
    .catch((error) => {
      console.error(error);
      ElMessage.error("获取产品列表失败");
    });
};

// 获取任务列表
const taskList = ref([]);
const getTaskList = () => {
  const token = token_stroage.value;
  const data = {
    token,
    page: 1,
    status: "0",
    search_type: 1,
    page_size: 9999,
  };
  axios
    .post("https://qianniu.bingdou.site/v1/cloud/client/task/list", data)
    .then((response) => {
      if (response.data && response.data.code === 0) {
        taskList.value = response.data.data.list;
      }
    })
    .catch((error) => {
      console.error(error);
      ElMessage.error("获取任务列表失败");
    });
};

// 获取任务列表

onMounted(async () => {
  await getstorage();
  await getCountFunction();
  await getOssUrl();
  await getProductList();
  await getTaskList();
  await getClassification();
  await getlabels();
});
// 数组随机返回一个值
const randomData = (array) => {
  const randomIndex = Math.floor(Math.random() * array.length);
  const randomValue = array[randomIndex];
  return randomValue;
};
//获取多个值
function getRandomElementsFromArray(arr, numElements) {
  // 克隆原始数组
  let tempArray = [...arr];
  let result = [];

  // 遍历指定个数
  for (let i = 0; i < numElements; i++) {
    // 如果数组已经没有更多元素，就退出循环
    if (tempArray.length === 0) {
      break;
    }
    // 随机选择一个索引
    let index = Math.floor(Math.random() * tempArray.length);
    // 从数组中取出该索引对应的元素
    result.push(tempArray[index]);
    // 将已经取出的元素从临时数组中移除
    tempArray.splice(index, 1);
  }

  return result;
}
// 生成一个基于当前日期和随机数的文艺文件名
const generateArtisticFilename = (blob) => {
  const fileExtension = blob.type.split("/").pop();
  const randomString = Math.random().toString(36).substring(7);
  const hashedFilename = md5(randomString) + "." + fileExtension;
  return hashedFilename;
};
// 循环执行的函数
const onCircleSend = async () => {
  loading.value = true;
  completed.value = 0;
  blob_list.value = [];
  const token = token_stroage.value;
  let task_id;
  try {
    const {
      number,
      sound,
      editor_name,
      video_name,
      product_id,
      cloud_task_id,
    } = form;
    let fragment_configuration = [];
    for (const key in videosDialog.dataList) {
      fragment_configuration.push(
        videosDialog.dataList[key]?.map((item) => {
          return {
            cover: item.cover,
            url: item.net_url,
          };
        })
      );
    }
    console.log("ssss", fragment_configuration);
    const taskres = await axios.post(
      "https://qianniu.bingdou.site/v2/task/create",
      {
        number,
        sound,
        token,
        editor_name,
        type: 1,
        video_name,
        product_id,
        cloud_task_id,
        tag_ids: selectedValues.value,
        fragment_configuration,
        ...radioData,
      },
      { timeout: 500 }
    );
    if (taskres && taskres.status !== 200) {
      return;
    }
    task_id = taskres.data.data.task_id;
  } catch (err) {
    console.log("err", err);
  }
  let hasUse = [];
  let downloadPath = null;
  const choice_video = (index, data) => {
    return data[index % data.length];
  };
  let nameArr = [];
  let noNewVideo = 0;
  let exitCount = 0;
  for (let i = 0; i < form.number; i++) {
    console.log("step1");
    let video_clip_fragment = [];
    let mergeList = [];
    console.log("single");
    console.log(single);
    if (single.value == 2) {
      // for (let j = i; j < single_count; j++) {
      const localfile = fileList.value[fragmentArr.value[0]] || [];
      const yunfile = videosDialog.dataList[fragmentArr.value[0]] || [];
      mergeList = getRandomElementsFromArray(
        [...localfile, ...yunfile],
        single_count.value
      );
      // }
      console.log("mergeList");
    } else {
      for (let j = 0; j < fragmentArr.value.length; j++) {
        console.log("step1-1");
        const localfile = fileList.value[fragmentArr.value[j]] || [];
        const yunfile = videosDialog.dataList[fragmentArr.value[j]] || [];
        let random;
        console.log(i);
        // console.log([...localfile, ...yunfile]);
        console.log("长度" + (i % [...localfile, ...yunfile].length));
        // if (j == 0) {
        //   console.log("aaa");
        //   random = [...localfile, ...yunfile][i % [...localfile, ...yunfile].length];
        // } else {
        //   console.log("aa");
        //   random = randomData([...localfile, ...yunfile]);
        // }
        console.log("hasUse");
        console.log(hasUse);
        if (!hasUse.hasOwnProperty(j)) {
          hasUse[j] = [];
          random =
            j == 0
              ? choice_video(i, [...localfile, ...yunfile])
              : randomData([...localfile, ...yunfile]);
          hasUse[j].push(random);
        } else {
          let newRandomData = difference([...localfile, ...yunfile], hasUse[j]);
          if (newRandomData.length == 0) {
            random =
              j == 0
                ? choice_video(i, [...localfile, ...yunfile])
                : randomData([...localfile, ...yunfile]);
          } else {
            random =
              j == 0
                ? choice_video(i, [...localfile, ...yunfile])
                : randomData(newRandomData);
            hasUse[j].push(random);
          }
        }

        console.log("step1-2");
        console.log("random");
        if (random) {
          mergeList.push(random);
        }
        console.log("step1-3");
      }
    }
    console.log("step2");
    let fileData;
    let buffer;
    if (mergeList.length === 0) {
      loading.value = false;
      ElMessage.warning("请先选择视频");
      return;
    }
    let mergeListName = '';
    let hasExit = false;
    if (mergeList.length > 0) {
      mergeList.forEach((item) => {
        const name = item.net_url || item.path
        mergeListName += name
      })
      if(nameArr.includes(mergeListName)) {
        hasExit = true;
        noNewVideo ++;
        exitCount ++;
      } else {
        nameArr.push(mergeListName);
        noNewVideo = 0;
      }
    }
    console.log('noNewVideo', noNewVideo)
    if(hasExit) {
      console.log('该视频已存在')
      continue;
    } 
    if(noNewVideo === 10) {
      break;
    }
    console.log('hasExit', exitCount)
    try {
      const { videoBlob, bufferData }  = await mergeVideosWithBackgroundMusic(
        mergeList,
        `output${i}.mp4`,
        i - exitCount + 1
      );
      fileData = videoBlob
      buffer = bufferData;
    } catch (err) {
      console.log("err", err);
    }
    console.log("step3");
    console.log("fileData", i);
    if (!fileData) continue;
    const artisticFilename = generateArtisticFilename(fileData);
    console.log("step4");
    const formData = new FormData();
    formData.append("file", fileData, artisticFilename);
    console.log("step5");
    if (saveWay.value === 2) {
      const result = await saveBlobVideo(
        buffer,
        artisticFilename,
        downloadPath
      );
      if (result) {
        downloadPath = result;
      }
    } else {
      if (oss_url.value) {
        try {
          const res = await axios.post(
            `${oss_url.value}/v1/file_upload`,
            formData,
            {
              headers: {
                "Content-Type": "multipart/form-data",
              },
            }
          );
          if (res && res.status !== 200) {
            return;
          }
          console.log("step6");
          const { convert_image, file_url, format } = res.data;
          console.log("file_url");
          video_clip_fragment.push({
            url: file_url,
            format,
            status: "1",
            cover: convert_image,
          });
          console.log("step7");
          try {
            const params = {
              task_id,
              is_over: true,
              video_clip_fragment,
              tag_ids: selectedValues.value,
              ...radioData,
            };
            const callres = await axios.post(
              "https://qianniu.bingdou.site/v2/task/video/result/callback",
              params,
              { timeout: 3000 }
            );
            if (callres && callres.data.code === 0) {
              ElMessage.success("创建成功");
            }
            console.log("step8");
          } catch (err) {
            ElMessage.error("创建失败");
            console.log("create_err", err);
          }
        } catch (err) {
          ElMessage.error("调用file_upload失败");
        }
        console.log(window.performance.memory);
      }
    }
  }
  loading.value = false;
  fileList.value = {};
  videosDialog.dataList = {};
  videosDialog.fragment = "A";
  yunloading.value = {};
  window.ipcRenderer.send("rmdir");
  await getCountFunction();
};
// 发布任务
const onHandleTask = async (formEl) => {
  if (!formEl) return;
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      if (radioData.one_class_id && !radioData.three_class_id) {
        ElMessage.warning("请选择三级分类");
        return;
      }
      onCircleSend();
    } else {
      console.log("error submit!", fields);
    }
  });
};
const handleRadioClick = (value) => {
  console.log("点击了单选框，值为：", value);
  if (value.level === 1) {
    radioData.one_class_id = value.id;
    radioData.two_class_id = "";
    radioData.three_class_id = "";
  }
  if (value.level === 2) {
    radioData.two_class_id = value.id;
    radioData.three_class_id = "";
  }
  if (value.level === 3) {
    radioData.three_class_id = value.id;
  }
};
const selectedItem = ref();
const radioData = reactive({});
</script>

<template>
  <div>如合成卡住，或合成后的视频片段少掉，请确认视频为H.264编码</div>
  <div>版本: 20240712</div>
  <br />
  <el-form :model="form" label-width="120px" :rules="rules" ref="ruleFormRef">
    <el-form-item label="次数" prop="number">
      <el-input-number
        v-model="form.number"
        class="mx-4"
        :min="1"
        controls-position="right"
      />
      <span style="margin-left: 20px">剩余生成次数: {{ count }}</span>
    </el-form-item>
    <el-form-item label="剪辑师名称" prop="editor_name">
      <el-input
        v-model="form.editor_name"
        placeholder="请输入剪辑师名称"
        style="width: 300px"
      />
    </el-form-item>
    <el-form-item label="视频名称" prop="video_name">
      <el-input
        v-model="form.video_name"
        placeholder="请输入视频名称"
        style="width: 300px"
      />
    </el-form-item>
    <el-form-item label="高级设置">
      <el-button @click="hightSet = !hightSet">
        <el-icon v-if="hightSet"><ArrowUp /></el-icon>
        <el-icon v-else><ArrowDown /></el-icon>
      </el-button>
    </el-form-item>
    <template v-if="hightSet">
      <el-form-item label="产品" prop="product_id">
        <el-select v-model="form.product_id" placeholder="请选择">
          <el-option
            v-for="item in productList"
            :key="item.id"
            :label="item.name"
            :value="item.id"
          ></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="任务" prop="cloud_task_id">
        <el-select v-model="form.cloud_task_id" placeholder="请选择">
          <el-option
            v-for="item in taskList"
            :key="item.id"
            :label="'ID' + item.id + ':' + item.product_names"
            :value="item.id"
            ><span v-for="(items, index) in item.product_names" :key="index"
              ><span v-if="index == 0">ID{{ item.id }}:</span>{{ items }}
            </span>
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="视频分类">
        <NestedRadio
          :classification="classification"
          @update:modelValue="handleRadioClick"
        />
      </el-form-item>
      <el-form-item label="公共标签">
        <div class="container">
          <div class="list">
            <div class="title">标签组</div>
            <div class="content">
              <div
                v-for="item in label_list"
                :key="item.id"
                class="label_content"
                @click="selectItem(item)"
                :class="{ selected: selectedLabel === item }"
              >
                {{ item.name }}
              </div>
            </div>
          </div>
          <div class="list">
            <div class="title">子标签</div>
            <div class="content">
              <el-checkbox-group v-model="selectedValues">
                <el-checkbox
                  :label="subItem.id"
                  v-for="subItem in selectedSubItems"
                  >{{ subItem.name }}</el-checkbox
                >
              </el-checkbox-group>
            </div>
          </div>
          <div class="list">
            <div class="title">已添加标签</div>
            <div class="content">
              <div
                v-for="value in selectedValues"
                :key="value"
                class="select_label"
              >
                {{ getSubItemName(value) }}
                <span class="delete" @click="deleteValue(value)"> x </span>
              </div>
            </div>
          </div>
        </div>
      </el-form-item>
    </template>
    <el-form-item label="单片段循环">
      <el-radio v-model="single" :label="1">否</el-radio>
      <el-radio v-model="single" :label="2">是</el-radio>
    </el-form-item>
    <el-form-item label="保存方式">
      <el-radio v-model="saveWay" :label="1">云服务器</el-radio>
      <el-radio v-model="saveWay" :label="2">本地</el-radio>
    </el-form-item>
    <el-form-item label="单片段镜头数">
      <el-input
        v-model="single_count"
        placeholder="单片段时选取的镜头数"
        style="width: 300px"
      />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onAddFragment">添加片段</el-button>
    </el-form-item>
    <el-form-item :label="`蒙版`">
      <template #label>
        <el-tooltip class="item" effect="dark" content="请选择一个 PNG 格式的透明图片，会全程覆盖在视频上，适合想修改视频md5/加水印/加批文使用。图片大小需要和视频一致" placement="top">
          <span>添加蒙版 ❓</span>
        </el-tooltip>
      </template>
      <el-upload
        class="upload-demo"
        action=""
        :on-remove="onUploadMaskRemove"
        :http-request="onhandleMaskRequest"
        :file-list="maskList"
        multiple
        accept=".png"
      >
        <el-button type="primary">选择蒙版图片</el-button>
      </el-upload>
    </el-form-item>
    <el-form-item label="视频素材BGM">
      <el-upload
        class="upload-demo"
        action=""
        :on-remove="onUploadMusicRemove"
        :http-request="onhandleMusicRequest"
        :file-list="musicList"
        multiple
        accept=".wav, .mp3, .ogg, .acc, .webm, .amr"
      >
        <el-button type="primary">选择素材BGM</el-button>
      </el-upload>
    </el-form-item>
    <div v-for="fragment in fragmentArr">
      <el-form-item :label="`视频素材${fragment}片段`">
        <el-button
          type="primary"
          @click="handleVisible(fragment)"
          style="margin-right: 10px"
          >添加云视频素材</el-button
        >
        <el-upload
          class="upload-demo"
          action=""
          :http-request="onhandleRequest"
          :file-list="fileList[fragment] || []"
          multiple
          :data="fragment"
          :show-file-list="false"
          accept=".mp4,.mov,.avi,.mkv,.wmv,.flv,.rmvb,.3gp,.webm,.mpeg"
        >
          <el-button type="primary">选择素材片段</el-button>
        </el-upload>
        <el-button style="margin-left: 10px;" @click="onDelFragVideo(fragment)">一键删除</el-button>
      </el-form-item>
      <el-form-item>
        <div class="list_box-item">
          <div v-if="yunloading[fragment]">加载云视频中...</div>
          <ul
            v-else-if="
              videosDialog.dataList[fragment] &&
              videosDialog.dataList[fragment].length > 0
            "
            class="video_list"
            style="margin-bottom: 0; margin-top: 0"
          >
            <li
              v-for="(item, index) in videosDialog.dataList[fragment]"
              :key="item.id"
              class="list__item"
            >
              <div class="list__item-info">
                <a class="list__item-name">
                  <div class="list__item-file-name">
                    (云视频) {{ item.name }}
                  </div>
                  <div @click="handleCyjbQsscFileRemove(item, fragment)">
                    <el-icon>
                      <Close />
                    </el-icon>
                  </div>
                </a>
              </div>
            </li>
          </ul>
          <ul
            v-if="fileList[fragment] && fileList[fragment].length > 0"
            class="video_list"
            style="margin-top: 0"
          >
            <li
              v-for="(item, index) in fileList[fragment]"
              :key="item.id"
              class="list__item"
            >
              <div class="list__item-info">
                <a class="list__item-name">
                  <div class="list__item-file-name">
                    （本地视频） {{ item.name }}
                  </div>
                  <div @click="onUploadRemove(item, fragment)">
                    <el-icon>
                      <Close />
                    </el-icon>
                  </div>
                </a>
              </div>
            </li>
          </ul>
        </div>
      </el-form-item>
    </div>
    <el-form-item label="合并成功数">
      <div style="width: 300px">
        <el-progress :percentage="progressWidth" :color="customColor">
          <el-button text>{{ completed }} / {{ form.number }}</el-button>
        </el-progress>
      </div>
    </el-form-item>
    <!-- <div v-if="blob_list.length > 0">
      <div v-for="item in blob_list" key="item">
        <video :src="item" controls class="custom-video"></video>
      </div>
    </div> -->
    <el-form-item v-if="fault_video.length > 0" label="错误片段">
      <div class="list_box-item">
        <ul style="margin-top: 0; padding: 0" class="no-bullet">
          <li v-for="item in [...new Set(fault_video)]" :key="item">
            {{ item }}
          </li>
        </ul>
      </div>
    </el-form-item>
    <el-form-item v-if="current.length > 0" label="合成片段">
      <div class="current_box-item">
        {{ current }}
      </div>
    </el-form-item>
    <el-form-item>
      <el-button
        type="primary"
        @click="onHandleTask(ruleFormRef)"
        :disabled="count < form.number || adjustloaded()"
        :loading="loading"
        >{{
          loading
            ? "正在请求阿里云接口中..."
            : count < form.number
            ? "生成次数不够"
            : adjustloaded()
            ? "下载云视频中"
            : "创建合成任务"
        }}</el-button
      >
    </el-form-item>
  </el-form>
  <SelectMaterialDialog
    v-if="videosDialog.visible && videosDialog.type === videoType.yunshipin"
    :visible="videosDialog.visible && videosDialog.type === videoType.yunshipin"
    :propData="{
      dataList: videosDialog.dataList[videosDialog.fragment]
        ? videosDialog.dataList[videosDialog.fragment].filter((item) => {
            return item.type === videoType.yunshipin;
          })
        : [],
    }"
    :fragment="videosDialog.fragment"
    @changeVisible="changeCyjbQsscVisible"
    @updateVideos="changeCyjbQsscData"
  />
</template>

<style scoped>
.custom-video {
  width: 300px;
  height: 150px;
}

.upload-demo {
  text-align: left;
}

:deep(.el-upload-list) {
  max-height: 200px;
  overflow-y: auto;
}

.fr {
  margin-left: 20px;
}

.list_box-item {
  max-height: 200px;
  overflow-y: auto;
  width: 310px;
  text-align: left;
}

.current_box-item {
  max-height: 200px;
  overflow-y: auto;
  width: 310px;
  text-align: left;
  word-break: break-all;
}

.video_list {
  width: 300px;
  list-style: none;
  padding-left: 0;
}

.list__item {
  transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
  font-size: 14px;
  color: #606266;
  margin-bottom: 5px;
  position: relative;
  box-sizing: border-box;
  border-radius: 4px;
  width: 100%;
}

.list__item-info {
  display: inline-flex;
  justify-content: center;
  flex-direction: column;
  width: calc(100% - 30px);
  margin-left: 4px;
}

.list__item-name {
  color: #606266;
  display: inline-flex;
  text-align: center;
  align-items: center;
  justify-content: space-between;
  padding: 0 4px;
  transition: color 0.3s;
  font-size: 14px;
}

.list__item-file-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.container {
  display: flex;
  height: 400px;
}

.title {
  font-weight: bold;
  margin-bottom: 10px;
  background: #f2f2f2;
  height: 40px;
  text-align: center;
}

.content {
  text-align: left;
  padding: 0 15px;
  height: calc(100% - 40px);
  overflow: auto;
}

.list {
  border: 1px solid #ccc;
  width: 234px;
  margin-right: 15px;
}

.list > div {
  margin-bottom: 5px;
}

.label_content {
  cursor: pointer;
}

.selected {
  color: #8b3dff;
}

.delete {
  cursor: pointer;
  margin-left: 5px;
  font-size: 16px;
  color: #a29d9d;
}

.content .el-checkbox {
  width: 100%;
}

.select_label {
  display: flex;
  justify-content: space-between;
}

.no-bullet {
  list-style-type: none;
}
</style>
